#region using directives

using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Client.UIHelper;

#endregion

namespace ClientForms
{
    /// <summary>
    /// Summary description for FeedbackForm.
    /// </summary>
    /// <exception cref="DataStoreAppConfigException">
    /// If the datastore has not been initialized before the form was created this exception will be thrown.
    /// </exception>
    public class FeedbackForm : Form
    {
        #region private form variables

        private string _status;

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private Container components = null;

        private DataStore dataStore;

        private TextBox email;
        private Label emailLabel;
        private ErrorProvider errNotifier;
        private TextBox firstname;
        private Label firstNameLabel;
        private Graphics grfx;
        private TextBox lastname;
        private Label lastNameLabel;
        private RichTextBox richTextBox1;

        private Label richTextLabel;
        private Serverprocessing sp;
        private Button submit;

        //holds the status of the form (Error, submitted, etc)

        #endregion

        #region constructor

        /// <summary>
        /// Constructor for the feedback form
        /// </summary>
        /// <exception cref="DataStoreAppConfigException">
        /// If the datastore has not been initialized before the form was created this exception will be thrown.
        /// </exception>
        public FeedbackForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();
            errNotifier = new ErrorProvider();
            dataStore = new DataStore(this);

            if (dataStore.PaymentSettings == null)
            {
                string message = "You Cannot use this form until a valid datastore has been received from the web service.";
                MessageBox.Show(message);
                Close();
                throw new DataStoreAppConfigException(message);
            }
        }

        #endregion

        #region dispose

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
                sp.Dispose();
            }
            base.Dispose(disposing);
        }

        #endregion

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.richTextBox1 = new System.Windows.Forms.RichTextBox();
            this.submit = new System.Windows.Forms.Button();
            this.firstname = new System.Windows.Forms.TextBox();
            this.lastname = new System.Windows.Forms.TextBox();
            this.email = new System.Windows.Forms.TextBox();
            this.firstNameLabel = new System.Windows.Forms.Label();
            this.lastNameLabel = new System.Windows.Forms.Label();
            this.emailLabel = new System.Windows.Forms.Label();
            this.richTextLabel = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // richTextBox1
            // 
            this.richTextBox1.AutoSize = true;
            this.richTextBox1.BackColor = System.Drawing.Color.LightGray;
            this.richTextBox1.Location = new System.Drawing.Point(170, 224);
            this.richTextBox1.MaxLength = 1024;
            this.richTextBox1.Name = "richTextBox1";
            this.richTextBox1.Size = new System.Drawing.Size(370, 104);
            this.richTextBox1.TabIndex = 4;
            this.richTextBox1.Text = "";
            // 
            // submit
            // 
            this.submit.AutoSize = true;
            this.submit.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.submit.Location = new System.Drawing.Point(297, 357);
            this.submit.Name = "submit";
            this.submit.Size = new System.Drawing.Size(114, 23);
            this.submit.TabIndex = 5;
            this.submit.Text = "Submit";
            this.submit.Click += new System.EventHandler(this.submit_Click);
            // 
            // firstname
            // 
            this.firstname.BackColor = System.Drawing.Color.LightGray;
            this.firstname.Location = new System.Drawing.Point(170, 112);
            this.firstname.MaxLength = 32;
            this.firstname.Name = "firstname";
            this.firstname.Size = new System.Drawing.Size(175, 20);
            this.firstname.TabIndex = 0;
            // 
            // lastname
            // 
            this.lastname.BackColor = System.Drawing.Color.LightGray;
            this.lastname.Location = new System.Drawing.Point(365, 112);
            this.lastname.MaxLength = 32;
            this.lastname.Name = "lastname";
            this.lastname.Size = new System.Drawing.Size(175, 20);
            this.lastname.TabIndex = 1;
            // 
            // email
            // 
            this.email.BackColor = System.Drawing.Color.LightGray;
            this.email.Location = new System.Drawing.Point(170, 168);
            this.email.MaxLength = 32;
            this.email.Name = "email";
            this.email.Size = new System.Drawing.Size(175, 20);
            this.email.TabIndex = 3;
            // 
            // firstNameLabel
            // 
            this.firstNameLabel.AutoSize = true;
            this.firstNameLabel.BackColor = System.Drawing.Color.Transparent;
            this.firstNameLabel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.firstNameLabel.Location = new System.Drawing.Point(170, 88);
            this.firstNameLabel.Name = "firstNameLabel";
            this.firstNameLabel.Size = new System.Drawing.Size(58, 13);
            this.firstNameLabel.TabIndex = 7;
            this.firstNameLabel.Text = "First Name:";
            // 
            // lastNameLabel
            // 
            this.lastNameLabel.AutoSize = true;
            this.lastNameLabel.BackColor = System.Drawing.Color.Transparent;
            this.lastNameLabel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.lastNameLabel.Location = new System.Drawing.Point(367, 88);
            this.lastNameLabel.Name = "lastNameLabel";
            this.lastNameLabel.Size = new System.Drawing.Size(57, 13);
            this.lastNameLabel.TabIndex = 8;
            this.lastNameLabel.Text = "Last Name:";
            // 
            // emailLabel
            // 
            this.emailLabel.AutoSize = true;
            this.emailLabel.BackColor = System.Drawing.Color.Transparent;
            this.emailLabel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.emailLabel.Location = new System.Drawing.Point(170, 144);
            this.emailLabel.Name = "emailLabel";
            this.emailLabel.Size = new System.Drawing.Size(35, 13);
            this.emailLabel.TabIndex = 9;
            this.emailLabel.Text = "E-mail:";
            // 
            // richTextLabel
            // 
            this.richTextLabel.AutoSize = true;
            this.richTextLabel.BackColor = System.Drawing.Color.Transparent;
            this.richTextLabel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.richTextLabel.Location = new System.Drawing.Point(237, 200);
            this.richTextLabel.Name = "richTextLabel";
            this.richTextLabel.Size = new System.Drawing.Size(201, 13);
            this.richTextLabel.TabIndex = 10;
            this.richTextLabel.Text = "Product Feedback (max 1024 characters)";
            // 
            // FeedbackForm
            // 
            this.AcceptButton = this.submit;
            this.BackColor = System.Drawing.Color.Silver;
            this.BackgroundImage = ClientForms.Resource.feedback;
            this.ClientSize = new System.Drawing.Size(570, 416);
            this.Controls.Add(this.richTextLabel);
            this.Controls.Add(this.emailLabel);
            this.Controls.Add(this.lastNameLabel);
            this.Controls.Add(this.firstNameLabel);
            this.Controls.Add(this.email);
            this.Controls.Add(this.lastname);
            this.Controls.Add(this.firstname);
            this.Controls.Add(this.submit);
            this.Controls.Add(this.richTextBox1);
            this.Name = "FeedbackForm";
            this.ShowInTaskbar = false;
            this.Text = "FeedbackForm";
            this.Load += new System.EventHandler(this.FeedbackForm_Load);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FeedbackForm_FormClosing);
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        #endregion

        #region form validation

        /// <summary>
        /// used to validate each entry box on the form
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        private bool ValidateField(Control control)
        {
            FormValidator.ControlValidator validator;

            if (control.Name == "email")
            {
                validator = new FormValidator.ControlValidator(FormValidator.Isemailvalidator);
            }
            else
            {
                validator = new FormValidator.ControlValidator(FormValidator.Hastextvalidator);
            }

            return FormValidator.Fieldisvalid(errNotifier, control, "Required Field", validator);
        }

        #endregion

        #region feedback form event handling

        private void FeedbackForm_Load(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// This is a required method to use the server processing class.  This gets called
        /// via an event from server processing to signal the UI that the processing is complete.
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FeedbackForm_ProccessingComplete(object sender, ProcessingCompletedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncString(SetFeedbackProcessingComplete);
            e.FormReference.Invoke(d, new object[] {e.Message});
        }

        /// <summary>
        /// Set the form state for processing complete and display the completion message.
        /// </summary>
        /// <param name="message">The completion message.</param>
        private void SetFeedbackProcessingComplete(string message)
        {
            foreach (Control c in Controls)
            {
                if (c.Name == "statusText")
                {
                    Controls.Remove(c);
                    break;
                }
            }

            var statusText = new TextBox();
            statusText.Multiline = true;
            statusText.BorderStyle = BorderStyle.None;
            statusText.ReadOnly = true;
            statusText.TabStop = false;
            statusText.BackColor = Color.White;
            statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
            statusText.Name = "statusText";
            statusText.Text = message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);
            submit.Enabled = false;
            Controls.Add(statusText);

            submit.Enabled = true;
            submit.Text = "Finish";

            submit.Focus();
        }

        /// <summary>
        /// This is a required method to use the server processing class.  Serverprocessing 
        /// communicates with the submit feedback web service and notifies the client with
        /// Error message via the ProcessingFailedEventArgs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FeedbackForm_ProccessingFailed(object sender, ProcessingFailedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncFailureInfo(SetFeedbackProcessingFailed);
            e.FormReference.Invoke(d, new object[] {e.FailureInformation});
        }

        /// <summary>
        /// Set the form for processing failed and display the failure message.
        /// </summary>
        /// <param name="message">The failure message to display to the user.</param>
        private void SetFeedbackProcessingFailed(FailureInfo failureInfo)
        {
            _status = "Error";
            foreach (Control c in Controls)
            {
                if (c.Name == "statusText")
                {
                    Controls.Remove(c);
                    break;
                }
            }

            var statusText = new TextBox();
            statusText.Multiline = true;
            statusText.BorderStyle = BorderStyle.None;
            statusText.ReadOnly = true;
            statusText.TabStop = false;
            statusText.BackColor = Color.White;
            statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
            statusText.Name = "statusText";
            statusText.Text = failureInfo.Message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);
            submit.Enabled = false;
            Controls.Add(statusText);

            submit.Enabled = true;
            submit.Text = "Finish";
            submit.Focus();

            if (failureInfo.Alert == FailureInfo.AlertType.Port)
            {
                MessageBox.Show("If the web service cannot be reached please " + "verify that the ASP .NET development port matches the port " + "configured in the application web reference and update as " + "necessary.  The application will need to be restarted after " + "the configuration change.");
            }
        }

        /// <summary>
        /// Handles the submit click event.  If form input validation is successful 
        /// server processing is contacted and info submitted via the submit feedback
        /// web service
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void submit_Click(object sender, EventArgs e)
        {
            if (_status == "submitted" || _status == "Error")
            {
                Close();
            }
            else
            {
                //first validate name and email fields to see if they are populated.  We do this because the IF statement
                //below will only run the first validation if it fails right there, and we want to validate all three fields
                //no matter what
                ValidateField(firstname);
                ValidateField(lastname);
                ValidateField(email);
                ValidateField(richTextBox1);

                //if all the form inputs are valid then proceed with server processing
                if (ValidateField(firstname) && ValidateField(lastname) && ValidateField(email) && ValidateField(richTextBox1))
                {
                    _status = "submitted";
                    firstname.Visible = false;
                    lastname.Visible = false;
                    email.Visible = false;
                    firstNameLabel.Visible = false;
                    lastNameLabel.Visible = false;
                    emailLabel.Visible = false;
                    richTextLabel.Visible = false;
                    richTextBox1.Visible = false;

                    var statusText = new TextBox();
                    statusText.Multiline = true;
                    statusText.BorderStyle = BorderStyle.None;
                    statusText.ReadOnly = true;
                    statusText.TabStop = false;
                    statusText.BackColor = Color.White;
                    statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
                    statusText.Name = "statusText";
                    statusText.Text = "Your feedback is being processed.  This may take a few moments.";
                    Graphics grfx = CreateGraphics();
                    SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
                    statusText.Width = 350;
                    statusText.Height = Convert.ToInt32(sizef.Height) + 50;
                    statusText.Location = new Point(170, (Height - statusText.Height)/2);
                    submit.Enabled = false;
                    Controls.Add(statusText);


                    submit.Enabled = false;


                    var feedbackInfo = new FeedbackInfo(dataStore.ProductName, dataStore.GetLicenseLevel.LicenseLevel, email.Text, firstname.Text, lastname.Text, richTextBox1.Text, dataStore.Devtoken, this);


                    //Create new serverProcessing class to handle web service calls
                    sp = new Serverprocessing(feedbackInfo);

                    //set up the event handlers for processing failed and complete
                    sp.Processingcomplete += new EventHandler<ProcessingCompletedEvent>(FeedbackForm_ProccessingComplete);
                    sp.Processingfailed += new EventHandler<ProcessingFailedEvent>(FeedbackForm_ProccessingFailed);

                    //start the web service on a seperate thread
                    var handleProcessingThreadStarter = new ThreadStart(sp.HandleFeedback);
                    var handleProcessingThread = new Thread(handleProcessingThreadStarter);
                    handleProcessingThread.Start();
                }
            }
        }


        private void FeedbackForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (sp != null)
            {
                sp.Cancelprocessing();
            }
        }

        #endregion
    }
}